package br.com.rookgraph.utils;

import java.text.DecimalFormat;

import br.com.rookgraph.gui.JanelaDeDuelo;

/**
 * Enum para controlar e configurar melhor a execução do algoritmo
 * 
 * @author Edmilson
 */
public enum ControleExecucao {
	
	/**
	 * Finaliza a execução quando a quantidade de iterações dop algoritmo excede o limite máximo de quantidade de iterações
	 */
	QUANTIDADE_ITERACOES ("Qtd. de Iterações") {

		@Override
		public Boolean continua() {
			return iteracao < qtdMaximaIteracoes;
		}
	},
	
	/**
	 * Finaliza a execução quando o resultado 1, do algoritmo 1, é pior (maior) que o resultado 2, do algoritmo 2. 
	 */
	PRIMEIRA_DERROTA ("Primeira Derrota") {

		@Override
		public Boolean continua() {
			return resultado1 <= resultado2;
		}
		
	};

	public abstract Boolean continua();
	
	public String descricao;
	public Integer iteracao;
	public Integer qtdMaximaIteracoes;
	public Integer resultado1;
	public Integer resultado2;
	
	public float tempo1;
	public float tempo2;
	
	public Integer qtdResultado1Melhor;
	public Integer qtdResultado2Melhor;
	public Integer qtdEmpates;
	
	ControleExecucao(String descricao) {
		this.descricao = descricao;
		zerarContadores();
	}
	
	/**
	 * Marca uma iteração na condição de parada. O primeiro parâmetro de resultado é o do algoritmo que deve ser superado.
	 * Deve ser usada quando a condição de parada é PRIMEIRA_DERROTA
	 * 
	 * @param resultado1
	 * @param resultado2
	 */
	public void marcarFimIteracao(Integer resultado1, Integer resultado2, float tempo1, float tempo2) {
		this.iteracao++;
		this.resultado1 = resultado1;
		this.resultado2 = resultado2;
		
		this.tempo1 = tempo1;
		this.tempo2 = tempo2;
		
		if (resultado1 < resultado2 && resultado1 != -1) {
			this.qtdResultado1Melhor++;
		} else if (resultado2 < resultado1 && resultado2 != -1) {
			this.qtdResultado2Melhor++;
		} else if (resultado1 == resultado2) {
			this.qtdEmpates++;
		}
	}
	
	/**
	 * Deve ser usada quando a condição de parada é QUANTIDADE_ITERACOES.
	 */
	public void marcarFimIteracao() {
		this.iteracao++;
	}
	
	public void exibirDadosIteracao() {
		if (resultado1 != resultado2) {
			JanelaDeDuelo.logarMesmaLinha("* ");
		} else {
			JanelaDeDuelo.logarMesmaLinha("  ");
		}
		
		DecimalFormat df = new DecimalFormat("#.00");
		
		JanelaDeDuelo.logar(iteracao + "\t" + resultado1 + " (" + df.format(tempo1) + ")" + "\t" + resultado2 + " (" + df.format(tempo2) + ")");
	}
	
	public Boolean isUltimaIteracao() {
		return this.qtdMaximaIteracoes != null & this.iteracao != null && this.iteracao.compareTo(this.qtdMaximaIteracoes) == 0;
	}
	
	public Integer getQtdMaximaIteracoes() {
		return qtdMaximaIteracoes;
	}

	public void setQtdMaximaIteracoes(Integer qtdMaximaIteracoes) {
		this.qtdMaximaIteracoes = qtdMaximaIteracoes;
	}

	public String getDescricao() {
		return descricao;
	}

	public Integer getQtdResultado1Melhor() {
		return qtdResultado1Melhor;
	}

	public Integer getQtdResultado2Melhor() {
		return qtdResultado2Melhor;
	}
	
	public Integer getQtdEmpates() {
		return qtdEmpates;
	}
	
	public static ControleExecucao clonar(ControleExecucao controle) {
		ControleExecucao c = ControleExecucao.valueOf(controle.name());
		
		return c;
	}

	public void zerarContadores() {
		this.iteracao = 0;
		this.resultado1 = 0;
		this.resultado2 = 0;
		
		this.qtdResultado1Melhor = 0;
		this.qtdResultado2Melhor = 0;
		this.qtdEmpates = 0;
	}

	@Override
	public String toString() {
		return descricao;
	}
	
}
